package com.dev.op.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dev.op.entity.Problem;
import com.dev.op.entity.Submission;
import com.dev.op.entity.TestCase;
import com.dev.op.service.RedisService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
public class RedisServiceImpl implements RedisService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    private static final String PROBLEM_PREFIX = "problem:";
    private static final String TEST_CASE_PREFIX = "testcase:";
    private static final String PROBLEMS_IN_PAGE_SIZE = "problem:page:size:";
    private static final String SUBMISSION_PREFIX = "submission:";
    @Override
    public Boolean saveProblem(Problem problem,long expireSeconds) {
        redisTemplate.opsForValue().set(PROBLEM_PREFIX + problem.getProblemId(), problem, Duration.ofSeconds(expireSeconds));
        return true;
    }

    @Override
    public Boolean saveProblemsInPageSize(Page<Problem> pageResult,long expireSeconds) {
        long page = pageResult.getCurrent();
        long size = pageResult.getSize();
        String key = PROBLEMS_IN_PAGE_SIZE + page+":"+size;
        // 设置缓存过期时间（如 10 分钟）
        redisTemplate.opsForValue().set(key, pageResult, Duration.ofSeconds(expireSeconds));
        return true;
    }

    @Override
    public Page<Problem> getProblemsInPage(int page, int size) {
        String key = PROBLEMS_IN_PAGE_SIZE + page+":"+size;
        Object obj = redisTemplate.opsForValue().get(key);
        if (obj == null) return null;
        // 反序列化为 MyBatis-Plus 的 Page<Problem>
        return objectMapper.convertValue(obj,
                new TypeReference<Page<Problem>>() {});
    }

    @Override
    public Boolean deleteLastPageOfProblemCache() {
        try {
            String pattern = PROBLEMS_IN_PAGE_SIZE + "*";
            ScanOptions scanOptions = ScanOptions.scanOptions().match(pattern).count(1000).build();
            Cursor<byte[]> cursor = redisTemplate.getConnectionFactory()
                    .getConnection().scan(scanOptions);
            String key = "";
            while (cursor.hasNext()) {
                key = new String(cursor.next());
            }
            boolean res = redisTemplate.delete(key);
            //System.out.println("删除结果："+res);
            return true;
        }
        catch (Exception e) {
            return false;
        }
    }

    @Override
    public Boolean deleteAllPageOfProblemCache() {
        try {
            String pattern = PROBLEMS_IN_PAGE_SIZE + "*";
            ScanOptions scanOptions = ScanOptions.scanOptions().match(pattern).count(1000).build();
            Cursor<byte[]> cursor = redisTemplate.getConnectionFactory()
                    .getConnection().scan(scanOptions);
            String key = "";
            while (cursor.hasNext()) {
                key = new String(cursor.next());
                redisTemplate.delete(key);
            }
            //System.out.println("删除结果："+res);
            return true;
        }
        catch (Exception e) {
            return false;
        }
    }


    @Override
    public Boolean saveTestCases(List<TestCase> testCases,long expireSeconds) {
        redisTemplate.opsForValue().set(TEST_CASE_PREFIX + testCases.get(0).getProblemId(), testCases, Duration.ofSeconds(expireSeconds));
        return true;
    }

    @Override
    public Boolean deleteProblem(String problemId) {
        return redisTemplate.delete(PROBLEM_PREFIX + problemId);
    }

    @Override
    public Problem getProblem(String problemId) {
        Object obj = redisTemplate.opsForValue().get(PROBLEM_PREFIX + problemId);
        if (obj instanceof Problem problem) {
            return problem;
        }
        return null;
    }

    @Override
    public List<TestCase> getTestCase(String problemId) {
        Object obj = redisTemplate.opsForValue().get(TEST_CASE_PREFIX + problemId);

        if (obj instanceof List<?> rawList) {
            // 判断第一个元素是不是 TestCase，否则说明是 Map 类型，需要手动转换
            if (!rawList.isEmpty() && rawList.get(0) instanceof TestCase) {
                @SuppressWarnings("unchecked")
                List<TestCase> testCases = (List<TestCase>) rawList;
                return testCases;
//            } else {
//                // 如果反序列化成 LinkedHashMap，则手动转换
//                ObjectMapper mapper = new ObjectMapper();
//                List<TestCase> converted = new ArrayList<>();
//                for (Object item : rawList) {
//                    TestCase tc = mapper.convertValue(item, TestCase.class);
//                    converted.add(tc);
//                }
//                return converted;
            }
        }
        return null;
    }

    @Override
    public Boolean deleteTestCase(String problemId) {
        return redisTemplate.delete(TEST_CASE_PREFIX + problemId);
    }

    @Override
    public Boolean saveSubmissionResult(Submission submission, long expireSecond) {
        String key = SUBMISSION_PREFIX + submission.getSubmissionId();
        redisTemplate.opsForValue().set(key, submission, Duration.ofSeconds(expireSecond));
        return true;
    }

    @Override
    public Submission getSubmission(String submissionId) {
        Object obj = redisTemplate.opsForValue().get(SUBMISSION_PREFIX + submissionId);
        if (obj instanceof Submission submission) {
            return submission;
        }
        return null;
    }

}
